package service

import (
	"crypto/tls"
	"noip_updator/common"
	"regexp"
	"strings"

	"github.com/go-mail/mail"
	"github.com/spf13/viper"
)

type MailService struct {
	host      string
	port      int
	myMail    string
	myPwd     string
	fromAlias string
	idleSec   uint
}

func NewMailService(alias string, idleSec uint) *MailService {
	common.Logger.Info("mail service init...")
	return &MailService{
		host:      viper.GetString("notification.mail.smtphost"),
		port:      viper.GetInt("notification.mail.port"),
		myMail:    viper.GetString("notification.mail.mymail"),
		myPwd:     viper.GetString("notification.mail.mypwd"),
		fromAlias: alias,
		idleSec:   idleSec,
	}
}

func (server *MailService) Listen(mailChan <-chan NotifyContent) {
	d := mail.NewDialer(server.host, server.port, server.myMail, server.myPwd)
	d.TLSConfig = &tls.Config{ServerName: server.host}
	d.StartTLSPolicy = mail.MandatoryStartTLS

	rawMailTo := strings.Split(
		strings.Trim(viper.GetString("notification.mail.mailto"), ","),
		",",
	)
	re := regexp.MustCompile(`[^@\.]+@[^@\.]+\.[^@\.]+`)
	var mailTo []string
	for _, to := range rawMailTo {
		to = strings.TrimSpace(to)
		if !re.MatchString(to) {
			continue
		}
		mailTo = append(mailTo, to)
	}
	for notifyContent := range mailChan {
		msg := server.CreateMsg(notifyContent.Subject, notifyContent.Content, mailTo)
		if err := d.DialAndSend(msg); err != nil {
			common.Logger.Errorf("DialAndSend err:%v", err)
			continue
		}
		common.Logger.Info("notify mail sent")
	}
}

func (server *MailService) CreateMsg(subject string, content string, mailto []string) (msg *mail.Message) {
	msg = mail.NewMessage(mail.SetEncoding(mail.Base64), mail.SetCharset("UTF-8"))
	msg.SetHeaders(map[string][]string{
		"From":    {msg.FormatAddress(server.myMail, server.fromAlias)},
		"To":      mailto,
		"Subject": {subject},
	})
	msg.SetBody("text/html", content)
	return
}
